<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="generator" content="rustdoc">
    <title>Wireless Firmware Update In Action on PineTime Smart Watch (nRF52)</title>

    
    <!-- Begin scripts/articles/*-header.html: Article Header for Custom Markdown files processed by rustdoc, like chip8.md -->
<meta property="og:title" 
    content="Wireless Firmware Update In Action on PineTime Smart Watch (nRF52)" 
    data-rh="true">
<meta property="og:description" 
    content="Observe step-by-step the Wireless Firmware Update running on PineTime Smart Watch (nRF52) with MCUBoot Bootloader, NimBLE Bluetooth LE Stack and Apache Mynewt" 
    data-rh="true">
<meta property="og:image" 
    content="https://lupyuen.github.io/images/dfutest-title.png">
<meta property="og:type" 
    content="article" data-rh="true">
<!-- End scripts/articles/*-header.html -->
<!-- Begin scripts/rustdoc-header.html: Header for Custom Markdown files processed by rustdoc, like chip8.md -->
<link rel="alternate" type="application/rss+xml" title="RSS Feed for lupyuen" href="/rss.xml" />
<link rel="stylesheet" type="text/css" href="../normalize.css">
<link rel="stylesheet" type="text/css" href="../rustdoc.css" id="mainThemeStyle">
<link rel="stylesheet" type="text/css" href="../dark.css">
<link rel="stylesheet" type="text/css" href="../light.css" id="themeStyle">
<script src="../storage.js"></script><noscript>
<link rel="stylesheet" href="../noscript.css"></noscript>
<link rel="shortcut icon" href="../favicon.ico">
<style type="text/css">
    #crate-search {
        background-image: url("../down-arrow.svg");
    }
    a {
        color: #77d;
    }
</style>
<!-- End scripts/rustdoc-header.html -->


</head>
<body class="rustdoc">
    <!--[if lte IE 8]>
    <div class="warning">
        This old browser is unsupported and will most likely display funky
        things.
    </div>
    <![endif]-->

        <!-- Begin scripts/rustdoc-before.html: Pre-HTML for Custom Markdown files processed by rustdoc, like chip8.md -->

    <!-- Begin Theme Picker -->
    <div class="theme-picker" style="left: 0"><button id="theme-picker" aria-label="Pick another theme!"><img src="../brush.svg"
        width="18" alt="Pick another theme!"></button>
        <div id="theme-choices"></div>
    </div>
    <script src="../theme.js"></script>
    <!-- Theme Picker -->

    <!-- End scripts/rustdoc-before.html -->
    

    <h1 class="title">Wireless Firmware Update In Action on PineTime Smart Watch (nRF52)</h1>
    <nav id="TOC"><ul>
<li><a href="#test-firmware-for-pinetime-firmware-update">1 Test Firmware for PineTime Firmware Update</a><ul></ul></li>
<li><a href="#update-relocate-the-interrupt-vector-table">2 Update: Relocate the Interrupt Vector Table</a><ul></ul></li>
<li><a href="#video-of-pinetime-firmware-update-test">3 Video of PineTime Firmware Update Test</a><ul></ul></li>
<li><a href="#test-log-for-pinetime-firmware-update">4 Test Log for PineTime Firmware Update</a><ul>
<li><a href="#before-pinetime-reboot">4.1 Before PineTime Reboot</a><ul></ul></li>
<li><a href="#after-pinetime-reboot">4.2 After PineTime Reboot</a><ul></ul></li></ul></li>
<li><a href="#pinetime-firmware-update-with-newt-mananger">5 PineTime Firmware Update with Newt Mananger</a><ul></ul></li>
<li><a href="#update-test-firmware-update-with-freertos">6 Update: Test Firmware Update with FreeRTOS</a><ul></ul></li>
<li><a href="#further-reading">7 Further Reading</a><ul></ul></li></ul></nav><p><img src="https://lupyuen.github.io/images/dfutest-title.png" alt="Wireless Firmware Update In Action on PineTime Smart Watch" /></p>
<p><em>Wireless Firmware Update In Action on PineTime Smart Watch</em></p>
<p>We have implemented a <strong>Wireless Firmware Update</strong> feature for <a href="https://wiki.pine64.org/index.php/PineTime"><strong>PineTime Smart Watch</strong></a> that's described here...</p>
<p><em><a href="https://lupyuen.github.io/pinetime-rust-mynewt/articles/mcuboot">&quot;MCUBoot Bootloader for PineTime Smart Watch (nRF52)&quot;</a></em></p>
<p><em><a href="https://lupyuen.github.io/pinetime-rust-mynewt/articles/dfu">&quot;Firmware Update over Bluetooth Low Energy on PineTime Smart Watch&quot;</a></em></p>
<p><em><a href="https://lupyuen.github.io/pinetime-rust-mynewt/articles/spiflash">&quot;Configure Mynewt for SPI Flash on PineTime Smart Watch (nRF52)&quot;</a></em></p>
<p>Now let's observe step-by-step the Wireless Firmware Update running on PineTime with <strong>MCUBoot Bootloader, NimBLE Bluetooth LE Stack and Apache Mynewt.</strong></p>
<p>Watch what happens in the PineTime Debug Log (captured with ST-Link Debugger and OpenOCD) as we perform Wireless Firmware Update in two ways...</p>
<ol>
<li>
<p>With the <a href="https://www.nordicsemi.com/Software-and-tools/Development-Tools/nRF-Connect-for-mobile"><strong>Nordic nRF Connect</strong></a> mobile app</p>
</li>
<li>
<p>With the <a href="http://mynewt.apache.org/latest/newtmgr/index.html"><strong>Newt Manager</strong></a> command-line tool</p>
</li>
</ol>
<p>Here's the video of the Firmware Update with nRF Connect...</p>
<ul>
<li>
<p><a href="https://youtu.be/thLhGUl9-CU">Watch on YouTube</a></p>
</li>
<li>
<p><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.3">Download the video</a></p>
</li>
</ul>
<p>Read on to learn what happens inside PineTime during Firmware Update.</p>
<h1 id="test-firmware-for-pinetime-firmware-update" class="section-header"><a href="#test-firmware-for-pinetime-firmware-update">1 Test Firmware for PineTime Firmware Update</a></h1>
<p>The PineTime firmware files used for testing Firmware Update are documented in the table below.</p>
<p>We provide 2 versions of each firmware file to be flashed...</p>
<ol>
<li>
<p><strong>Arm Semihosting Enabled:</strong> These files should be selected if you're debugging with ST-Link or Raspberry Pi. They will display debugging messages on the Arm Semihosting Console via OpenOCD. These files will hang when used with JLink.</p>
</li>
<li>
<p><strong>Arm Semihosting Disabled:</strong> Files named <code>nosemi</code> should be selected if you're debugging with JLink. They will not display debugging messages via Arm Semihosting.</p>
</li>
</ol>
<p>The Semihosting Build Options are defined here: <a href="https://github.com/lupyuen/pinetime-rust-mynewt/blob/ota2/targets/nrf52_boot/pkg.yml">Bootloader Options</a>, <a href="https://github.com/lupyuen/pinetime-rust-mynewt/blob/ota2/targets/nrf52_my_sensor/pkg.yml">Application Firmware Options</a></p>
<p>Before testing Firmware Update, the MCUBoot Bootloader AND Mynewt Firmware should be flashed manually to PineTime (via ST-Link or Raspberry Pi). Select either the Semihosting version or the JLink version...</p>
<table><thead><tr><th align="left">Firmware Component</th><th align="left">Version</th><th align="left">Binary File</th><th align="left">From</th><th align="left">Flash To</th><th align="left">At Address</th><th align="left">Remarks</th></tr></thead><tbody>
<tr><td align="left">MCUBoot Bootloader for Semihosting</td><td align="left">1.0.0</td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/download/v4.1.7/mynewt.elf.bin"><code>mynewt</code><br><code>.elf.bin</code></a></td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.7"><code>v4.1.7</code></a></td><td align="left">Internal Flash ROM</td><td align="left"><code>0x0000 0000</code></td><td align="left">Use this bootloader if you're debugging with ST-Link or Raspberry Pi (Semihosting is enabled)</td></tr>
<tr><td align="left">MCUBoot Bootloader for JLink</td><td align="left">1.0.0</td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/download/v4.1.7/mynewt_nosemi.elf.bin"><code>mynewt</code><br><code>-nosemi</code><br><code>.elf.bin</code></a></td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.7"><code>v4.1.7</code></a></td><td align="left">Internal Flash ROM</td><td align="left"><code>0x0000 0000</code></td><td align="left">Use this bootloader if you're debugging with JLink (Semihosting is disabled)</td></tr>
<tr><td align="left">Mynewt Firmware for Semihosting</td><td align="left">1.0.0</td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/download/v4.1.1/my_sensor_app.img"><code>my_sensor_app</code><br><code>.img</code></a></td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.1"><code>v4.1.1</code></a></td><td align="left">Internal Flash ROM</td><td align="left"><code>0x0000 8000</code></td><td align="left">Contains MCUBoot Image Header and Mynewt OS with Rust. Shows &quot;<code>I AM PINETIME</code>&quot; (Semihosting is enabled)</td></tr>
<tr><td align="left">Mynewt Firmware for JLink</td><td align="left">1.0.0</td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/download/v4.1.4/my_sensor_app_nosemi.img"><code>my_sensor_app</code><br><code>_nosemi</code><br><code>.img</code></a></td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.4"><code>v4.1.4</code></a></td><td align="left">Internal Flash ROM</td><td align="left"><code>0x0000 8000</code></td><td align="left">Contains MCUBoot Image Header and Mynewt OS with Rust. Shows &quot;<code>I AM PINETIME</code>&quot; (Semihosting is disabled)</td></tr>
<tr><td align="left">Boot Graphic (Optional)</td><td align="left">1.0.0</td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/download/v4.1.1/boot-graphic.bin"><code>boot-graphic</code><br><code>.bin</code></a></td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.1"><code>v4.1.1</code></a></td><td align="left">External SPI Flash</td><td align="left"><code>0x0000 0000</code></td><td align="left">Hand-drawn PineTime Logo in RGB565 format, 240 x 240 pixels, 2 bytes per pixel</td></tr>
</tbody></table>
<p>[ Update: The above links have been updated with the new MCUBoot Bootloader that relocates the Vector Table ]</p>
<p>If MCUBoot Bootloader for Semihosting doesn't start on PineTime, try using MCUBoot Bootloader for JLink.</p>
<p>While testing Firmware Update, download and select one of the following Firmware Images in nRF Connect (or Newt Manager)...</p>
<table><thead><tr><th align="left">Firmware Image</th><th align="left">Version</th><th align="left">Binary File</th><th align="left">From</th><th align="left">Flash To</th><th align="left">At Address</th><th align="left">Remarks</th></tr></thead><tbody>
<tr><td align="left">Mynewt Firmware for Semihosting</td><td align="left">1.1.0</td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/download/v4.1.2/my_sensor_app_1.1.img"><code>my_sensor_app</code><br><code>_1.1.img</code></a></td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.2"><code>v4.1.2</code></a></td><td align="left">External SPI Flash</td><td align="left"><code>0x0004 0000</code></td><td align="left">Contains MCUBoot Image Header and Mynewt OS with Rust. Shows &quot;<code>PINETIME 1.1</code>&quot; (Semihosting is enabled)</td></tr>
<tr><td align="left">Mynewt Firmware for JLink</td><td align="left">1.1.0</td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/download/v4.1.2/my_sensor_app_nosemi_1.1.img"><code>my_sensor_app</code><br><code>_nosemi</code><br><code>_1.1.img</code></a></td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.2"><code>v4.1.2</code></a></td><td align="left">External SPI Flash</td><td align="left"><code>0x0004 0000</code></td><td align="left">Contains MCUBoot Image Header and Mynewt OS with Rust. Shows &quot;<code>PINETIME 1.1</code>&quot; (Semihosting is disabled)</td></tr>
<tr><td align="left">Mynewt Firmware for Semihosting</td><td align="left">1.2.0</td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/download/v4.1.2/my_sensor_app_1.2.img"><code>my_sensor_app</code><br><code>_1.2.img</code></a></td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.2"><code>v4.1.2</code></a></td><td align="left">External SPI Flash</td><td align="left"><code>0x0004 0000</code></td><td align="left">Contains MCUBoot Image Header and Mynewt OS with Rust. Shows &quot;<code>PINETIME 1.2</code>&quot; (Semihosting is enabled)</td></tr>
<tr><td align="left">Mynewt Firmware for JLink</td><td align="left">1.2.0</td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/download/v4.1.2/my_sensor_app_nosemi_1.2.img"><code>my_sensor_app</code><br><code>_nosemi</code><br><code>_1.2.img</code></a></td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.2"><code>v4.1.2</code></a></td><td align="left">External SPI Flash</td><td align="left"><code>0x0004 0000</code></td><td align="left">Contains MCUBoot Image Header and Mynewt OS with Rust. Shows &quot;<code>PINETIME 1.2</code>&quot; (Semihosting is disabled)</td></tr>
<tr><td align="left">FreeRTOS Firmware</td><td align="left">1.1.0</td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/download/v4.1.5/jf.bin"><code>jf.bin</code></a></td><td align="left"><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.5"><code>v4.1.5</code></a></td><td align="left">External SPI Flash</td><td align="left"><code>0x0004 0000</code></td><td align="left">Contains MCUBoot Image Header and <a href="https://github.com/JF002/Pinetime">FreeRTOS</a>. Shows a digital watch face (Semihosting is disabled)</td></tr>
</tbody></table>
<p>We provide two Mynewt firmware versions (1.1.0 and 1.2.0) for testing firmware swapping. The Mynewt firmware files were built from <a href="https://github.com/lupyuen/pinetime-rust-mynewt/tree/ota2"><code>pinetime-rust-mynewt/ota2</code></a> and the build version numbers were specified in <a href="https://github.com/lupyuen/pinetime-rust-mynewt/blob/ota2/scripts/nrf52/image-app.sh"><code>scripts/nrf52/image-app.sh</code></a></p>
<p>To use the Firmware Image Files with the nRF Connect App, we need to rename the file extension from <code>.img</code> to <code>.bin</code> after downloading (e.g. <code>my_sensor_app_1.1.bin</code>)</p>
<p>Note that <code>.bin</code> files may be found in the <a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.1"><code>v4.1.1</code></a> and <a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.2"><code>v4.1.2</code></a> downloads, but these <code>.bin</code> files should not be used for Firmware Updates because they don't have the MCUBoot Image Header.</p>
<p>So always download the <code>.img</code> files and then rename them to <code>.bin</code>.</p>
<p>The <code>.img</code> files were created with the <code>imgtool.py</code> command-line tool <a href="https://lupyuen.github.io/pinetime-rust-mynewt/articles/dfu">described here</a>.</p>
<p>Note that the Mynewt firmware files were built with the <a href="https://github.com/lupyuen/pinetime-rust-mynewt/tree/ota2"><code>ota2</code> branch of <code>pinetime-rust-mynewt</code></a> branch which supports MCUBoot (instead of the default <code>master</code> branch which uses the Stub Bootloader).</p>
<p>The <code>ota2</code> branch has a conflict in the MCUBoot version numbers. <a href="https://lupyuen.github.io/pinetime-rust-mynewt/articles/mcuboot#download-source-files">Check this link</a> for the instructions to download MCUBoot version 1.5.0.</p>
<p><em>Can we customise the Boot Graphic?</em></p>
<p>Use this tool to convert a 240 x 240 PNG file to RGB565: <a href="https://github.com/lupyuen/pinetime-graphic"><code>github.com/lupyuen/pinetime-graphic</code></a></p>
<p>Unfortunately we don't have an easy way to flash the RGB565 Boot Graphic to External SPI Flash at address <code>0x0</code>. The flashing needs to be done in C like this: <a href="https://github.com/lupyuen/pinetime-rust-mynewt/blob/ota2/libs/pinetime_boot/src/write.c"><code>libs/pinetime_boot/write.c</code></a></p>
<h1 id="update-relocate-the-interrupt-vector-table" class="section-header"><a href="#update-relocate-the-interrupt-vector-table">2 Update: Relocate the Interrupt Vector Table</a></h1>
<p>[ Update: This section is new ]</p>
<p>While testing <a href="https://github.com/JF002/Pinetime">FreeRTOS</a> with MCUBoot, we encountered a problem with the Interrupt Vector Table...</p>
<p><em>What is the Interrupt Vector Table?</em></p>
<p>It's a table of pointers to functions that will handle Interrupts (like from the Touch Controller) and Exceptions (like invalid memory access).</p>
<p>Arm Cortex-M firmware must have this table located at the start of Internal Flash ROM (address <code>0x0</code>).</p>
<p>With MCUBoot Bootloader, we will have two Vector Tables...</p>
<ol>
<li>
<p><strong>Vector Table for MCUBoot:</strong> Used when the bootloader runs. Located at Flash ROM Address <code>0x0</code></p>
</li>
<li>
<p><strong>Vector Table for Application Firmware:</strong> Used when the Application Firmware runs. Located at Flash ROM Address <code>0x8020</code></p>
</li>
</ol>
<p><em>Will the two Vector Tables have conflicts?</em></p>
<p>Yes, because most Application Firmware is written with the assumption that the Vector Table is at address <code>0x0</code>.</p>
<p>Now that the Application Firmware Vector Table is located elsewhere at <code>0x8020</code>, we need to switch the Vector Tables correctly.</p>
<p><em>How do we switch between the two Vector Tables?</em></p>
<p>We need to <strong>Relocate the Vector Table.</strong> When the MCUBoot Bootloader is about to start the Application Firmware, it copies the firmware's Vector Table (from <code>0x8020</code>) to a page-aligned address in Internal Flash ROM: <code>0x7F00</code></p>
<p>Then MCUBoot sets the VTOR Register in the Arm CPU's System Control Block to point to the Relocated Vector Table: <code>0x7F00</code>. The code for Vector Table Relocation is here: <a href="https://github.com/lupyuen/pinetime-rust-mynewt/blob/ota2/libs/pinetime_boot/src/pinetime_boot.c#L102-L132"><code>libs/pinetime_boot/src/pinetime_boot.c</code></a></p>
<pre><code class="language-c">/// Relocate the Arm Vector Table from vector_table to relocated_vector_table.
/// relocated_vector_table must be aligned to 0x100 page boundary.
static void relocate_vector_table(void *vector_table, void *relocated_vector_table) {
    uint32_t *current_location = (uint32_t *) vector_table;
    uint32_t *new_location     = (uint32_t *) relocated_vector_table;
    if (new_location == current_location) { return; }  //  No need to relocate
    //  Check whether we need to copy the vectors.
    int vector_diff = 0;  //  Non-zero if a vector is different
    for (int i = 0; i &lt; NVIC_NUM_VECTORS; i++) {
        if (new_location[i] != current_location[i]) {
            vector_diff = 1;
            break;
        }
    }
    //  If we need to copy the vectors, erase the flash ROM and write the vectors.
    if (vector_diff) {
        hal_flash_erase(  //  Erase...
            0,            //  Internal Flash ROM
            (uint32_t) relocated_vector_table,  //  At the relocated address
            0x100         //  Assume that we erase an entire page
        );
        hal_flash_write(  //  Write...
            0,            //  Internal Flash ROM
            (uint32_t) relocated_vector_table,  //  To the relocated address
            vector_table, //  From the original address
            0x100         //  Assume that we copy an entire page
        );  
    }
    //  Point VTOR Register in the System Control Block to the relocated vector table.
    *SCB_VTOR = (uint32_t) relocated_vector_table;
}
</code></pre>
<p>Here is the updated MCUBoot Bootloader that correctly relocates the Interrupt Vector Table before starting the Application Firmware...</p>
<p><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.7"><code>pinetime-rust-mynewt/releases/tag/v4.1.7</code></a></p>
<p><a href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/BABIFJFG.html">Arm Documentation on Vector Table</a></p>
<p><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.5">More about the Vector Table</a></p>
<h1 id="video-of-pinetime-firmware-update-test" class="section-header"><a href="#video-of-pinetime-firmware-update-test">3 Video of PineTime Firmware Update Test</a></h1>
<p>Here's the video of the Wireless Firmware Upgrade from version 1.0.0 to 1.1.0...</p>
<ul>
<li>
<p><a href="https://youtu.be/thLhGUl9-CU">Watch on YouTube</a></p>
</li>
<li>
<p><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.3">Download the video</a></p>
</li>
</ul>
<p><img src="https://lupyuen.github.io/images/dfutest-title.png" alt="Wireless Firmware Update In Action on PineTime Smart Watch" /></p>
<p><strong>Left:</strong> PineTime Smart Watch</p>
<p><strong>Centre:</strong> Debug Log from PineTime, captured with ST-Link debugger and OpenOCD</p>
<p><strong>Right:</strong> Android Phone with <a href="https://www.nordicsemi.com/Software-and-tools/Development-Tools/nRF-Connect-for-mobile">Nordic nRF Connect</a> mobile app</p>
<p>What happens step by step, by timecode...</p>
<ul>
<li>
<p><code>00:00</code> - PineTime is preloaded with...</p>
<ol>
<li>
<p>MCUBoot Bootloader for Semihosting</p>
</li>
<li>
<p>Application Firmware Image v1.0.0</p>
</li>
<li>
<p>Boot Graphic</p>
</li>
</ol>
<p>The Application Firmware is running, showing &quot;<code>I AM PINETIME</code>&quot;</p>
<p>ST-Link debugger is connected, showing the debug log. <code>Swap type</code> is set to <code>perm</code> because we have previously used nRF Connect to mark the Firmware image as &quot;Confirmed&quot;...</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
[<span class="ident">INF</span>] <span class="ident">Primary</span> <span class="ident">image</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">good</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x2</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x1</span>
[<span class="ident">INF</span>] <span class="ident">Scratch</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">bad</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x2</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x2</span>
[<span class="ident">INF</span>] <span class="ident">Boot</span> <span class="ident">source</span>: <span class="ident">none</span>
[<span class="ident">INF</span>] <span class="ident">Swap</span> <span class="kw">type</span>: <span class="ident">perm</span></pre></div>
<p><em>From <a href="https://github.com/JuulLabs-OSS/mcuboot/blob/master/boot/mynewt/src/main.c#L239-L245"><code>mcuboot/main.c</code></a></em></p>
</li>
<li>
<p><code>00:03</code> - Start the <a href="https://www.nordicsemi.com/Software-and-tools/Development-Tools/nRF-Connect-for-mobile">Nordic nRF Connect</a> mobile app on an Android phone.</p>
<p>Tap on <code>pinetime</code> and the <code>DFU</code> icon to start the Firmware Update</p>
</li>
<li>
<p><code>00:12</code> - <strong>Select the firmware file</strong> to be flashed...</p>
<p>Application Firmware Image v1.1.0 <br>
<code>my_sensor_app_1.1.img</code> <br>
Downloaded from <a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.2"><code>v4.1.2</code></a> </p>
<p>We renamed the file to <code>my_sensor_app_1.1.bin</code> after downloading, because nRF Connect only accepts <code>.bin</code> files.</p>
<p>Wireless upload to PineTime begins. PineTime receives the firmware file via the NimBLE Bluetooth Stack and the MCU Manager Library.</p>
<p>The new firmware will be staged in PineTime's External SPI Flash at address <code>0x0004 0000</code>.</p>
</li>
<li>
<p><code>02:11</code> - <strong>Upload completed</strong>. PineTime attempts to reboot, but because we are running ST-Link, the reboot attempt was caught by the debugger. We restart the OpenOCD debugger to reboot PineTime manually.</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">target</span> <span class="ident">halted</span> <span class="ident">due</span> <span class="ident">to</span> <span class="ident">breakpoint</span>, <span class="ident">current</span> <span class="ident">mode</span>: <span class="ident">Thread</span> 
<span class="ident">xPSR</span>: <span class="number">0x61000000</span> <span class="ident">pc</span>: <span class="number">0x000081d8</span> <span class="ident">psp</span>: <span class="number">0x20006a78</span>, <span class="ident">semihosting</span></pre></div>
<p>nRF Connect took 60 seconds to upload the 205 KB firmware file to PineTime. We'll see later that Newt Manager can upload the firmware file faster: 31 seconds.</p>
</li>
<li>
<p><code>02:13</code> - PineTime <strong>reboots</strong>. MCUBoot Bootloader starts.</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">Starting</span> <span class="ident">Bootloader</span>...</pre></div>
<p><em>From <a href="https://github.com/lupyuen/pinetime-rust-mynewt/blob/ota2/libs/pinetime_boot/src/pinetime_boot.c#L35"><code>libs/pinetime_boot/pinetime_boot.c</code></a></em></p>
</li>
<li>
<p><code>02:14</code> - MCUBoot Bootloader renders the <strong>Boot Graphic</strong> (hand-drawn PineTime logo) in under 1 second</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">Displaying</span> <span class="ident">image</span>...
<span class="ident">Image</span> <span class="ident">displayed</span></pre></div>
<p><em>From <a href="https://github.com/lupyuen/pinetime-rust-mynewt/blob/ota2/libs/pinetime_boot/src/display.c#L112-L183"><code>libs/pinetime_boot/display.c</code></a></em></p>
<p>MCUBoot checks whether the watch button is pressed, for <strong>Manual Firmware Rollback.</strong> (The checking of Manual Firmware Rollback is presently simulated, pending implementation)</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">Button</span>: <span class="number">0</span></pre></div>
<p><em>From <a href="https://github.com/lupyuen/pinetime-rust-mynewt/blob/ota2/libs/pinetime_boot/src/pinetime_boot.c#L45"><code>libs/pinetime_boot/pinetime_boot.c</code></a></em></p>
</li>
<li>
<p><code>02:16</code> - <strong>MCUBoot starts swapping</strong> the new firmware (External SPI Flash) with the old firmware (Internal Flash ROM)</p>
</li>
<li>
<p><code>02:30</code> - <strong>MCUBoot swapping completed.</strong> New firmware is now in Internal Flash ROM, old firmware is now in External SPI Flash.</p>
<p><code>Swap type: test</code> means that the swapping to new firmware has been completed successfully.</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
[<span class="ident">INF</span>] <span class="ident">Primary</span> <span class="ident">image</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">good</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x3</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x1</span>
[<span class="ident">INF</span>] <span class="ident">Scratch</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">bad</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x2</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x2</span>
[<span class="ident">INF</span>] <span class="ident">Boot</span> <span class="ident">source</span>: <span class="ident">none</span>
[<span class="ident">INF</span>] <span class="ident">Swap</span> <span class="kw">type</span>: <span class="ident">test</span></pre></div>
<p><em>From <a href="https://github.com/JuulLabs-OSS/mcuboot/blob/master/boot/mynewt/src/main.c#L239-L245"><code>mcuboot/main.c</code></a></em></p>
</li>
<li>
<p><code>02:30</code> - MCUBoot waits 5 seconds and checks whether the watch button is pressed, for <strong>Manual Firmware Rollback</strong> (Simulated)</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">Button</span>: <span class="number">0</span>
<span class="ident">Button</span>: <span class="number">0</span></pre></div>
<p><em>From <a href="https://github.com/lupyuen/pinetime-rust-mynewt/blob/ota2/libs/pinetime_boot/src/pinetime_boot.c#L54-L58"><code>libs/pinetime_boot/pinetime_boot.c</code></a></em></p>
</li>
<li>
<p><code>02:36</code> - MCUBoot starts the <strong>New Application Firmware</strong></p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">Bootloader</span> <span class="ident">done</span></pre></div>
<p><em>From <a href="https://github.com/lupyuen/pinetime-rust-mynewt/blob/ota2/libs/pinetime_boot/src/pinetime_boot.c#L61"><code>pinetime_boot/pinetime_boot.c</code></a></em></p>
<p>Mynewt Application Firmware starts the Temperature Stub Driver and dsplays the Hardware ID</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">TMP</span> <span class="ident">create</span> <span class="ident">temp_stub_0</span>
<span class="ident">NET</span> <span class="ident">hwid</span> <span class="number">4a</span> <span class="ident">f8</span> <span class="ident">cf</span> <span class="number">95</span> <span class="number">6a</span> <span class="ident">be</span> <span class="ident">c1</span> <span class="ident">f6</span> <span class="number">89</span> <span class="ident">ba</span> <span class="number">12</span> <span class="number">1a</span> 
<span class="ident">NET</span> <span class="ident">standalone</span> <span class="ident">node</span> </pre></div>
<p><em>From <a href="https://github.com/lupyuen/pinetime-rust-mynewt/blob/ota2/libs/temp_stub/src/creator.c#L69-L70"><code>libs/temp_stub/creator.c</code></a>, <a href="https://github.com/lupyuen/pinetime-rust-mynewt/blob/ota2/libs/sensor_network/src/sensor_network.c#L369-L370"><code>libs/sensor_network/sensor_network.c</code></a></em></p>
<p>Mynewt Application Firmware reads the Internal Flash ROM and External SPI Flash for testing </p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">Testing</span> <span class="ident">flash</span>...
<span class="ident">Read</span> <span class="ident">Internal</span> <span class="ident">Flash</span> <span class="ident">ROM</span>...
<span class="ident">Read</span> <span class="number">0x0</span> <span class="op">+</span> <span class="number">20</span>
<span class="number">0x0000</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x01</span> <span class="number">0x20</span> <span class="number">0xd9</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0008</span>: <span class="number">0x35</span> <span class="number">0x01</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x37</span> <span class="number">0x01</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0010</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0018</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="ident">Read</span> <span class="ident">External</span> <span class="ident">SPI</span> <span class="ident">Flash</span>...
<span class="ident">Read</span> <span class="number">0x0</span> <span class="op">+</span> <span class="number">20</span>
<span class="number">0x0000</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0008</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0010</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0018</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="ident">Flash</span> <span class="ident">OK</span></pre></div>
<p><em>From <a href="https://github.com/lupyuen/pinetime-rust-mynewt/blob/ota2/apps/my_sensor_app/src/flash_test.c#L218-L298"><code>apps/my_sensor_app/flash_test.c</code></a></em></p>
</li>
<li>
<p><code>02:37</code> - Mynewt Application Firmware <strong>resets the Backlight and Display Controller,</strong> causing the screen to blank (needs to be fixed)</p>
</li>
<li>
<p><code>02:43</code> - Mynewt Application Firmware <strong>switches on the Backlight</strong> via the Rust driver for ST7789 Display Controller. The hand-drawn PineTime logo previously rendered is now visible.</p>
<p>Mynewt Application Firmware <strong>erases the screen very slowly</strong> via the Rust driver for ST7789 Display Controller</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">Rust</span> <span class="ident">test</span> <span class="ident">display</span></pre></div>
<p><em>From <a href="https://github.com/lupyuen/pinetime-rust-mynewt/blob/ota2/rust/app/src/display.rs#L23"><code>rust/app/display.rs</code></a></em></p>
</li>
<li>
<p><code>02:55</code> - Mynewt Application Firmware <strong>renders some shapes</strong> and the message &quot;<code>PINETIME 1.1</code>&quot;</p>
</li>
</ul>
<h1 id="test-log-for-pinetime-firmware-update" class="section-header"><a href="#test-log-for-pinetime-firmware-update">4 Test Log for PineTime Firmware Update</a></h1>
<p>Here's the PineTime log for the above test, captured from the ST-Link OpenOCD debugger...</p>
<h2 id="before-pinetime-reboot" class="section-header"><a href="#before-pinetime-reboot">4.1 Before PineTime Reboot</a></h2>
<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">Starting</span> <span class="ident">Bootloader</span>...
<span class="ident">Displaying</span> <span class="ident">image</span>...
<span class="ident">Image</span> <span class="ident">displayed</span>
<span class="ident">Button</span>: <span class="number">0</span>
[<span class="ident">INF</span>] <span class="ident">Primary</span> <span class="ident">image</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">good</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x2</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x1</span>
[<span class="ident">INF</span>] <span class="ident">Scratch</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">bad</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x2</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x2</span>
[<span class="ident">INF</span>] <span class="ident">Boot</span> <span class="ident">source</span>: <span class="ident">none</span>
[<span class="ident">INF</span>] <span class="ident">Swap</span> <span class="kw">type</span>: <span class="ident">perm</span>
<span class="ident">Button</span>: <span class="number">0</span>
<span class="ident">Button</span>: <span class="number">0</span>
<span class="ident">Bootloader</span> <span class="ident">done</span>
<span class="ident">TMP</span> <span class="ident">create</span> <span class="ident">temp_stub_0</span>
<span class="ident">NET</span> <span class="ident">hwid</span> <span class="number">4a</span> <span class="ident">f8</span> <span class="ident">cf</span> <span class="number">95</span> <span class="number">6a</span> <span class="ident">be</span> <span class="ident">c1</span> <span class="ident">f6</span> <span class="number">89</span> <span class="ident">ba</span> <span class="number">12</span> <span class="number">1a</span> 
<span class="ident">NET</span> <span class="ident">standalone</span> <span class="ident">node</span> 
<span class="ident">Testing</span> <span class="ident">flash</span>...
<span class="ident">Read</span> <span class="ident">Internal</span> <span class="ident">Flash</span> <span class="ident">ROM</span>...
<span class="ident">Read</span> <span class="number">0x0</span> <span class="op">+</span> <span class="number">20</span>
  <span class="number">0x0000</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x01</span> <span class="number">0x20</span> <span class="number">0xd9</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
  <span class="number">0x0008</span>: <span class="number">0x35</span> <span class="number">0x01</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x37</span> <span class="number">0x01</span> <span class="number">0x00</span> <span class="number">0x00</span> 
  <span class="number">0x0010</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
  <span class="number">0x0018</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="ident">Read</span> <span class="ident">External</span> <span class="ident">SPI</span> <span class="ident">Flash</span>...
<span class="ident">Read</span> <span class="number">0x0</span> <span class="op">+</span> <span class="number">20</span>
  <span class="number">0x0000</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
  <span class="number">0x0008</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
  <span class="number">0x0010</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
  <span class="number">0x0018</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="ident">Flash</span> <span class="ident">OK</span>
<span class="ident">Rust</span> <span class="ident">test</span> <span class="ident">display</span>
<span class="ident">target</span> <span class="ident">halted</span> <span class="ident">due</span> <span class="ident">to</span> <span class="ident">breakpoint</span>, <span class="ident">current</span> <span class="ident">mode</span>: <span class="ident">Thread</span> 
<span class="ident">xPSR</span>: <span class="number">0x61000000</span> <span class="ident">pc</span>: <span class="number">0x000081d8</span> <span class="ident">psp</span>: <span class="number">0x20006a78</span>, <span class="ident">semihosting</span></pre></div>
<h2 id="after-pinetime-reboot" class="section-header"><a href="#after-pinetime-reboot">4.2 After PineTime Reboot</a></h2>
<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">Starting</span> <span class="ident">Bootloader</span>...
<span class="ident">Displaying</span> <span class="ident">image</span>...
<span class="ident">Image</span> <span class="ident">displayed</span>
<span class="ident">Button</span>: <span class="number">0</span>
[<span class="ident">INF</span>] <span class="ident">Primary</span> <span class="ident">image</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">good</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x3</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x1</span>
[<span class="ident">INF</span>] <span class="ident">Scratch</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">bad</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x2</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x2</span>
[<span class="ident">INF</span>] <span class="ident">Boot</span> <span class="ident">source</span>: <span class="ident">none</span>
[<span class="ident">INF</span>] <span class="ident">Swap</span> <span class="kw">type</span>: <span class="ident">test</span>
<span class="ident">Button</span>: <span class="number">0</span>
<span class="ident">Button</span>: <span class="number">0</span>
<span class="ident">Bootloader</span> <span class="ident">done</span>
<span class="ident">TMP</span> <span class="ident">create</span> <span class="ident">temp_stub_0</span>
<span class="ident">NET</span> <span class="ident">hwid</span> <span class="number">4a</span> <span class="ident">f8</span> <span class="ident">cf</span> <span class="number">95</span> <span class="number">6a</span> <span class="ident">be</span> <span class="ident">c1</span> <span class="ident">f6</span> <span class="number">89</span> <span class="ident">ba</span> <span class="number">12</span> <span class="number">1a</span> 
<span class="ident">NET</span> <span class="ident">standalone</span> <span class="ident">node</span> 
<span class="ident">Testing</span> <span class="ident">flash</span>...
<span class="ident">Read</span> <span class="ident">Internal</span> <span class="ident">Flash</span> <span class="ident">ROM</span>...
<span class="ident">Read</span> <span class="number">0x0</span> <span class="op">+</span> <span class="number">20</span>
  <span class="number">0x0000</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x01</span> <span class="number">0x20</span> <span class="number">0xd9</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
  <span class="number">0x0008</span>: <span class="number">0x35</span> <span class="number">0x01</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x37</span> <span class="number">0x01</span> <span class="number">0x00</span> <span class="number">0x00</span> 
  <span class="number">0x0010</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
  <span class="number">0x0018</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="ident">Read</span> <span class="ident">External</span> <span class="ident">SPI</span> <span class="ident">Flash</span>...
<span class="ident">Read</span> <span class="number">0x0</span> <span class="op">+</span> <span class="number">20</span>
  <span class="number">0x0000</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
  <span class="number">0x0008</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
  <span class="number">0x0010</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
  <span class="number">0x0018</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="ident">Flash</span> <span class="ident">OK</span>
<span class="ident">Rust</span> <span class="ident">test</span> <span class="ident">display</span></pre></div>
<h1 id="pinetime-firmware-update-with-newt-mananger" class="section-header"><a href="#pinetime-firmware-update-with-newt-mananger">5 PineTime Firmware Update with Newt Mananger</a></h1>
<p>To understand the Firmware Update in detail, we'll use the <a href="http://mynewt.apache.org/latest/newtmgr/index.html"><strong>Newt Manager</strong></a> command-line tool to reproduce each step of the Firmware Update.  The shell script may be found here: <a href="https://github.com/lupyuen/pinetime-rust-mynewt/blob/master/scripts/nrf52/test-dfu.sh"><code>test-dfu.sh</code></a></p>
<p>For this test we're using Ubuntu 20.04 on Raspberry Pi 4, connected to a USB Bluetooth Dongle (because the onboard Bluetooth adapter is not detected by Ubuntu).</p>
<ol>
<li>
<p><strong>Build Newt Manager</strong> on Raspberry Pi...</p>
<p>We'll build the Newt Manager tool, which is a Go program that works best on Linux. Source code for Newt Manager: <a href="https://github.com/apache/mynewt-newtmgr"><code>mynewt-newtmgr</code></a></p>
<pre><code class="language-bash"># Build Newt Manager on Raspberry Pi
cd ~/go
mkdir -p src/mynewt.apache.org
cd src/mynewt.apache.org/
git clone https://github.com/apache/mynewt-newtmgr
mv mynewt-newtmgr newtmgr
cd newtmgr/newtmgr
export GO111MODULE=on
go build
</code></pre>
</li>
<li>
<p><strong>Create a Connection Profile</strong> in Newt Manager</p>
<p>PineTime sets and advertises <code>pinetime</code> as its Bluetooth LE device name. We create a Connection Profile that uses this peer name to communicate with the device over Bluetooth LE...</p>
<pre><code class="language-bash">cd ~/go/src/mynewt.apache.org/newtmgr/newtmgr
sudo ./newtmgr conn add pinetime type=ble connstring=&quot;peer_name=pinetime&quot;
</code></pre>
<p>We'll see...</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">Connection</span> <span class="ident">profile</span> <span class="ident">pinetime</span> <span class="ident">successfully</span> <span class="ident">added</span></pre></div>
</li>
<li>
<p><strong>Connect to PineTime and List Firmware Images</strong></p>
<p>Next we connect to PineTime over Bluetooth LE and list the firmware images stored in PineTime's Internal Flash ROM (Active Firmware) and External SPI Flash (Standby Firmware). </p>
<p>Note that we're using the <code>--loglevel debug</code> option, which shows all Bluetooth request and response packets.</p>
<pre><code class="language-bash">sudo ./newtmgr image list -c pinetime --loglevel debug
</code></pre>
<p>We'll see...</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">DEBU</span>[<span class="number">2020</span><span class="op">-</span><span class="number">05</span><span class="op">-</span><span class="number">19</span> <span class="number">04</span>:<span class="number">46</span>:<span class="number">13.693</span>] <span class="ident">Using</span> <span class="ident">connection</span> <span class="ident">profile</span>: <span class="ident">name</span><span class="op">=</span><span class="ident">pinetime</span> <span class="kw">type</span><span class="op">=</span><span class="ident">ble</span> <span class="ident">connstring</span><span class="op">=</span><span class="ident">peer_name</span><span class="op">=</span><span class="ident">pinetime</span> 
<span class="ident">DEBU</span>[<span class="number">2020</span><span class="op">-</span><span class="number">05</span><span class="op">-</span><span class="number">19</span> <span class="number">04</span>:<span class="number">46</span>:<span class="number">14.023</span>] <span class="ident">Connecting</span> <span class="ident">to</span> <span class="ident">peer</span>                           
<span class="ident">DEBU</span>[<span class="number">2020</span><span class="op">-</span><span class="number">05</span><span class="op">-</span><span class="number">19</span> <span class="number">04</span>:<span class="number">46</span>:<span class="number">14.244</span>] <span class="ident">Exchanging</span> <span class="ident">MTU</span>                               
<span class="ident">DEBU</span>[<span class="number">2020</span><span class="op">-</span><span class="number">05</span><span class="op">-</span><span class="number">19</span> <span class="number">04</span>:<span class="number">46</span>:<span class="number">14.256</span>] <span class="ident">Exchanged</span> <span class="ident">MTU</span>; <span class="ident">ATT</span> <span class="ident">MTU</span> <span class="op">=</span> <span class="number">256</span>                 
<span class="ident">DEBU</span>[<span class="number">2020</span><span class="op">-</span><span class="number">05</span><span class="op">-</span><span class="number">19</span> <span class="number">04</span>:<span class="number">46</span>:<span class="number">14.256</span>] <span class="ident">Discovering</span> <span class="ident">profile</span>                          
<span class="ident">DEBU</span>[<span class="number">2020</span><span class="op">-</span><span class="number">05</span><span class="op">-</span><span class="number">19</span> <span class="number">04</span>:<span class="number">46</span>:<span class="number">14.503</span>] <span class="ident">Subscribing</span> <span class="ident">to</span> <span class="ident">NMP</span> <span class="ident">response</span> <span class="ident">characteristic</span>   
<span class="ident">DEBU</span>[<span class="number">2020</span><span class="op">-</span><span class="number">05</span><span class="op">-</span><span class="number">19</span> <span class="number">04</span>:<span class="number">46</span>:<span class="number">14.518</span>] {<span class="ident">add</span><span class="op">-</span><span class="ident">nmp</span><span class="op">-</span><span class="ident">listener</span>} [<span class="ident">bll_sesn</span>.<span class="ident">go</span>:<span class="number">392</span>] <span class="ident">seq</span><span class="op">=</span><span class="number">66</span>  
<span class="ident">DEBU</span>[<span class="number">2020</span><span class="op">-</span><span class="number">05</span><span class="op">-</span><span class="number">19</span> <span class="number">04</span>:<span class="number">46</span>:<span class="number">14.519</span>] <span class="ident">Encoded</span> <span class="kw-2">&amp;</span>{<span class="ident">NmpBase</span>:{<span class="ident">hdr</span>:{<span class="ident">Op</span>:<span class="number">0</span> <span class="ident">Flags</span>:<span class="number">0</span> <span class="ident">Len</span>:<span class="number">0</span> <span class="ident">Group</span>:<span class="number">1</span> <span class="ident">Seq</span>:<span class="number">66</span> <span class="ident">Id</span>:<span class="number">0</span>}}} <span class="ident">to</span>:
<span class="number">00000000</span>  <span class="ident">a0</span>                                                <span class="op">|</span>.<span class="op">|</span> 
<span class="ident">DEBU</span>[<span class="number">2020</span><span class="op">-</span><span class="number">05</span><span class="op">-</span><span class="number">19</span> <span class="number">04</span>:<span class="number">46</span>:<span class="number">14.519</span>] <span class="ident">Encoded</span>:
<span class="number">00000000</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">01</span> <span class="number">00</span> <span class="number">01</span> <span class="number">42</span> <span class="number">00</span>  <span class="ident">a0</span>                       <span class="op">|</span>......<span class="ident">B</span>..<span class="op">|</span> 
<span class="ident">DEBU</span>[<span class="number">2020</span><span class="op">-</span><span class="number">05</span><span class="op">-</span><span class="number">19</span> <span class="number">04</span>:<span class="number">46</span>:<span class="number">14.519</span>] <span class="ident">Tx</span> <span class="ident">NMP</span> <span class="ident">request</span>: <span class="number">00000000</span>  <span class="number">00</span> <span class="number">00</span> <span class="number">00</span> <span class="number">01</span> <span class="number">00</span> <span class="number">01</span> <span class="number">42</span> <span class="number">00</span>  <span class="ident">a0</span>                       <span class="op">|</span>......<span class="ident">B</span>..<span class="op">|</span> 
<span class="ident">DEBU</span>[<span class="number">2020</span><span class="op">-</span><span class="number">05</span><span class="op">-</span><span class="number">19</span> <span class="number">04</span>:<span class="number">46</span>:<span class="number">14.542</span>] <span class="ident">rx</span> <span class="ident">nmp</span> <span class="ident">response</span>: <span class="number">00000000</span>  <span class="number">01</span> <span class="number">00</span> <span class="number">00</span> <span class="number">86</span> <span class="number">00</span> <span class="number">01</span> <span class="number">42</span> <span class="number">00</span>  <span class="ident">bf</span> <span class="number">66</span> <span class="number">69</span> <span class="number">6d</span> <span class="number">61</span> <span class="number">67</span> <span class="number">65</span> <span class="number">73</span>  <span class="op">|</span>......<span class="ident">B</span>..<span class="ident">fimages</span><span class="op">|</span>
<span class="number">00000010</span>  <span class="number">9f</span> <span class="ident">bf</span> <span class="number">64</span> <span class="number">73</span> <span class="number">6c</span> <span class="number">6f</span> <span class="number">74</span> <span class="number">00</span>  <span class="number">67</span> <span class="number">76</span> <span class="number">65</span> <span class="number">72</span> <span class="number">73</span> <span class="number">69</span> <span class="number">6f</span> <span class="number">6e</span>  <span class="op">|</span>..<span class="ident">dslot</span>.<span class="ident">gversion</span><span class="op">|</span>
<span class="number">00000020</span>  <span class="number">65</span> <span class="number">31</span> <span class="number">2e</span> <span class="number">30</span> <span class="number">2e</span> <span class="number">30</span> <span class="number">64</span> <span class="number">68</span>  <span class="number">61</span> <span class="number">73</span> <span class="number">68</span> <span class="number">58</span> <span class="number">20</span> <span class="number">70</span> <span class="number">3e</span> <span class="ident">bb</span>  <span class="op">|</span><span class="ident">e1</span>.<span class="number">0.0dhashX</span> <span class="ident">p</span><span class="op">&gt;</span>.<span class="op">|</span>
<span class="number">00000030</span>  <span class="ident">f8</span> <span class="number">11</span> <span class="number">45</span> <span class="number">8b</span> <span class="number">1f</span> <span class="ident">ad</span> <span class="number">18</span> <span class="number">9e</span>  <span class="number">64</span> <span class="ident">e3</span> <span class="ident">a5</span> <span class="ident">e0</span> <span class="ident">f8</span> <span class="number">09</span> <span class="ident">cb</span> <span class="ident">e6</span>  <span class="op">|</span>..<span class="ident">E</span>.....<span class="ident">d</span>.......<span class="op">|</span>
<span class="number">00000040</span>  <span class="ident">ba</span> <span class="ident">d8</span> <span class="number">83</span> <span class="ident">c7</span> <span class="number">6b</span> <span class="number">3d</span> <span class="ident">d7</span> <span class="number">12</span>  <span class="number">79</span> <span class="number">1c</span> <span class="number">82</span> <span class="number">2f</span> <span class="ident">b5</span> <span class="number">68</span> <span class="number">62</span> <span class="number">6f</span>  <span class="op">|</span>....<span class="ident">k</span><span class="op">=</span>..<span class="ident">y</span>..<span class="op">/</span>.<span class="ident">hbo</span><span class="op">|</span>
<span class="number">00000050</span>  <span class="number">6f</span> <span class="number">74</span> <span class="number">61</span> <span class="number">62</span> <span class="number">6c</span> <span class="number">65</span> <span class="ident">f5</span> <span class="number">67</span>  <span class="number">70</span> <span class="number">65</span> <span class="number">6e</span> <span class="number">64</span> <span class="number">69</span> <span class="number">6e</span> <span class="number">67</span> <span class="ident">f4</span>  <span class="op">|</span><span class="ident">otable</span>.<span class="ident">gpending</span>.<span class="op">|</span>
<span class="number">00000060</span>  <span class="number">69</span> <span class="number">63</span> <span class="number">6f</span> <span class="number">6e</span> <span class="number">66</span> <span class="number">69</span> <span class="number">72</span> <span class="number">6d</span>  <span class="number">65</span> <span class="number">64</span> <span class="ident">f5</span> <span class="number">66</span> <span class="number">61</span> <span class="number">63</span> <span class="number">74</span> <span class="number">69</span>  <span class="op">|</span><span class="ident">iconfirmed</span>.<span class="ident">facti</span><span class="op">|</span>
<span class="number">00000070</span>  <span class="number">76</span> <span class="number">65</span> <span class="ident">f5</span> <span class="number">69</span> <span class="number">70</span> <span class="number">65</span> <span class="number">72</span> <span class="number">6d</span>  <span class="number">61</span> <span class="number">6e</span> <span class="number">65</span> <span class="number">6e</span> <span class="number">74</span> <span class="ident">f4</span> <span class="ident">ff</span> <span class="ident">ff</span>  <span class="op">|</span><span class="ident">ve</span>.<span class="ident">ipermanent</span>...<span class="op">|</span>
<span class="number">00000080</span>  <span class="number">6b</span> <span class="number">73</span> <span class="number">70</span> <span class="number">6c</span> <span class="number">69</span> <span class="number">74</span> <span class="number">53</span> <span class="number">74</span>  <span class="number">61</span> <span class="number">74</span> <span class="number">75</span> <span class="number">73</span> <span class="number">00</span> <span class="ident">ff</span>        <span class="op">|</span><span class="ident">ksplitStatus</span>..<span class="op">|</span> 
<span class="ident">DEBU</span>[<span class="number">2020</span><span class="op">-</span><span class="number">05</span><span class="op">-</span><span class="number">19</span> <span class="number">04</span>:<span class="number">46</span>:<span class="number">14.542</span>] <span class="ident">Received</span> <span class="ident">nmp</span> <span class="ident">rsp</span>: <span class="kw-2">&amp;</span>{<span class="ident">NmpBase</span>:{<span class="ident">hdr</span>:{<span class="ident">Op</span>:<span class="number">1</span> <span class="ident">Flags</span>:<span class="number">0</span> <span class="ident">Len</span>:<span class="number">134</span> <span class="ident">Group</span>:<span class="number">1</span> <span class="ident">Seq</span>:<span class="number">66</span> <span class="ident">Id</span>:<span class="number">0</span>}} <span class="ident">Rc</span>:<span class="number">0</span> <span class="ident">Images</span>:[{<span class="ident">NmpBase</span>:{<span class="ident">hdr</span>:{<span class="ident">Op</span>:<span class="number">0</span> <span class="ident">Flags</span>:<span class="number">0</span> <span class="ident">Len</span>:<span class="number">0</span> <span class="ident">Group</span>:<span class="number">0</span> <span class="ident">Seq</span>:<span class="number">0</span> <span class="ident">Id</span>:<span class="number">0</span>}} <span class="ident">Image</span>:<span class="number">0</span> <span class="ident">Slot</span>:<span class="number">0</span> <span class="ident">Version</span>:<span class="number">1.0</span>.<span class="number">0</span> <span class="ident">Hash</span>:[<span class="number">112</span> <span class="number">62</span> <span class="number">187</span> <span class="number">248</span> <span class="number">17</span> <span class="number">69</span> <span class="number">139</span> <span class="number">31</span> <span class="number">173</span> <span class="number">24</span> <span class="number">158</span> <span class="number">100</span> <span class="number">227</span> <span class="number">165</span> <span class="number">224</span> <span class="number">248</span> <span class="number">9</span> <span class="number">203</span> <span class="number">230</span> <span class="number">186</span> <span class="number">216</span> <span class="number">131</span> <span class="number">199</span> <span class="number">107</span> <span class="number">61</span> <span class="number">215</span> <span class="number">18</span> <span class="number">121</span> <span class="number">28</span> <span class="number">130</span> <span class="number">47</span> <span class="number">181</span>] <span class="ident">Bootable</span>:<span class="bool-val">true</span> <span class="ident">Pending</span>:<span class="bool-val">false</span> <span class="ident">Confirmed</span>:<span class="bool-val">true</span> <span class="ident">Active</span>:<span class="bool-val">true</span> <span class="ident">Permanent</span>:<span class="bool-val">false</span>}] <span class="ident">SplitStatus</span>:<span class="ident">N</span><span class="op">/</span><span class="ident">A</span>} 
<span class="ident">DEBU</span>[<span class="number">2020</span><span class="op">-</span><span class="number">05</span><span class="op">-</span><span class="number">19</span> <span class="number">04</span>:<span class="number">46</span>:<span class="number">14.543</span>] {<span class="ident">remove</span><span class="op">-</span><span class="ident">nmp</span><span class="op">-</span><span class="ident">listener</span>} [<span class="ident">bll_sesn</span>.<span class="ident">go</span>:<span class="number">392</span>] <span class="ident">seq</span><span class="op">=</span><span class="number">66</span> 
<span class="ident">Images</span>:
<span class="ident">image</span><span class="op">=</span><span class="number">0</span> <span class="ident">slot</span><span class="op">=</span><span class="number">0</span>
    <span class="ident">version</span>: <span class="number">1.0</span>.<span class="number">0</span>
    <span class="ident">bootable</span>: <span class="bool-val">true</span>
    <span class="ident">flags</span>: <span class="ident">active</span> <span class="ident">confirmed</span>
    <span class="ident">hash</span>: <span class="number">703ebbf811458b1fad189e64e3a5e0f809cbe6bad883c76b3dd712791c822fb5</span>
<span class="ident">Split</span> <span class="ident">status</span>: <span class="ident">N</span><span class="op">/</span><span class="ident">A</span> (<span class="number">0</span>)    </pre></div>
<p>This shows that the Active Firmware Image (version 1.0.0) in Internal Flash ROM has been set as Confirmed, which means that the existing firmware is running OK.</p>
</li>
<li>
<p><strong>Upload a Firmware Image to PineTime</strong></p>
<p>We upload to PineTime version 1.1.0 of the firmware image: <code>my_sensor_app_1.1.img</code> (previously downloaded from <a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.2"><code>pinetime-rust-mynewt/releases/tag/v4.1.2</code></a>)</p>
<pre><code class="language-bash">sudo ./newtmgr image upload -c pinetime \
   ~/my_sensor_app_1.1.img 
</code></pre>
<p>The upload completes in 31 seconds for the 205 KB firmware file.</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
    <span class="number">205.27</span> <span class="ident">KiB</span> <span class="op">/</span> <span class="number">205.27</span> <span class="ident">KiB</span> [<span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span><span class="op">=</span>] <span class="number">100.00</span><span class="op">%</span> <span class="number">6.47</span> <span class="ident">KiB</span><span class="op">/</span><span class="ident">s</span> <span class="number">31s</span>
<span class="ident">Done</span></pre></div>
<p>We list the firmware images again...</p>
<pre><code class="language-bash">sudo ./newtmgr image list -c pinetime
</code></pre>
<p>The new firmware as been loaded to Slot 1 (External SPI Flash). Note that the <code>flags</code> are empty.</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">Images</span>:
<span class="ident">image</span><span class="op">=</span><span class="number">0</span> <span class="ident">slot</span><span class="op">=</span><span class="number">0</span>
    <span class="ident">version</span>: <span class="number">1.0</span>.<span class="number">0</span>
    <span class="ident">bootable</span>: <span class="bool-val">true</span>
    <span class="ident">flags</span>: <span class="ident">active</span> <span class="ident">confirmed</span>
    <span class="ident">hash</span>: <span class="number">703ebbf811458b1fad189e64e3a5e0f809cbe6bad883c76b3dd712791c822fb5</span>
<span class="ident">image</span><span class="op">=</span><span class="number">0</span> <span class="ident">slot</span><span class="op">=</span><span class="number">1</span>
    <span class="ident">version</span>: <span class="number">1.1</span>.<span class="number">0</span>
    <span class="ident">bootable</span>: <span class="bool-val">true</span>
    <span class="ident">flags</span>: 
    <span class="ident">hash</span>: <span class="number">66a23f4f8f5766b5150711eb8c7c4be326cebabef37429fd21879f6e0eacffe5</span>
<span class="ident">Split</span> <span class="ident">status</span>: <span class="ident">N</span><span class="op">/</span><span class="ident">A</span> (<span class="number">0</span>)</pre></div>
<p>The hash value for the new firmware is <code>66a2...</code>. We'll use this in the next step.</p>
</li>
<li>
<p><strong>Set the New Firmware Image Status to Pending</strong> </p>
<p>The new firmware has been uploaded to the External SPI Flash but is not yet active. 
We run the <code>image test</code> command to set the firmware status to Pending so that it will be started after rebooting...</p>
<pre><code class="language-bash">sudo ./newtmgr image test -c pinetime \
   66a23f4f8f5766b5150711eb8c7c4be326cebabef37429fd21879f6e0eacffe5
</code></pre>
<p>Note that <code>66a2...</code> is the hash value for the new firmware, obtained from the previous step.</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">Images</span>:
<span class="ident">image</span><span class="op">=</span><span class="number">0</span> <span class="ident">slot</span><span class="op">=</span><span class="number">0</span>
    <span class="ident">version</span>: <span class="number">1.0</span>.<span class="number">0</span>
    <span class="ident">bootable</span>: <span class="bool-val">true</span>
    <span class="ident">flags</span>: <span class="ident">active</span> <span class="ident">confirmed</span>
    <span class="ident">hash</span>: <span class="number">703ebbf811458b1fad189e64e3a5e0f809cbe6bad883c76b3dd712791c822fb5</span>
<span class="ident">image</span><span class="op">=</span><span class="number">0</span> <span class="ident">slot</span><span class="op">=</span><span class="number">1</span>
    <span class="ident">version</span>: <span class="number">1.1</span>.<span class="number">0</span>
    <span class="ident">bootable</span>: <span class="bool-val">true</span>
    <span class="ident">flags</span>: <span class="ident">pending</span>
    <span class="ident">hash</span>: <span class="number">66a23f4f8f5766b5150711eb8c7c4be326cebabef37429fd21879f6e0eacffe5</span>
<span class="ident">Split</span> <span class="ident">status</span>: <span class="ident">N</span><span class="op">/</span><span class="ident">A</span> (<span class="number">0</span>)</pre></div>
<p>The <code>flags</code> for the new firmware is now set to <code>pending</code>. MCUBoot will swap the new firmware into Internal Flash ROM on reboot.</p>
</li>
<li>
<p><strong>Reboot PineTime</strong></p>
<p>We reboot PineTime to test the new firmware. Here's the PineTime debug log captured with ST-Link and OpenOCD...</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">Starting</span> <span class="ident">Bootloader</span>...
<span class="ident">Displaying</span> <span class="ident">image</span>...
<span class="ident">Image</span> <span class="ident">displayed</span>
<span class="ident">Button</span>: <span class="number">0</span>
[<span class="ident">INF</span>] <span class="ident">Primary</span> <span class="ident">image</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">unset</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x3</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x3</span>
[<span class="ident">INF</span>] <span class="ident">Scratch</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">unset</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x3</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x3</span>
[<span class="ident">INF</span>] <span class="ident">Boot</span> <span class="ident">source</span>: <span class="ident">primary</span> <span class="ident">slot</span>
[<span class="ident">INF</span>] <span class="ident">Swap</span> <span class="kw">type</span>: <span class="ident">test</span>
<span class="ident">Button</span>: <span class="number">0</span></pre></div>
<p>Note that <code>Swap type</code> is set to <code>test</code>, which means that MCUBoot has swapped in the new firmware from External SPI Flash into Internal Flash ROM.</p>
<p>The old firmware has been swapped out to External SPI Flash.</p>
<p>But somehow the new firmware failed to start (maybe because the ST-Link debugger was still attached).  PineTime rebooted by itself and showed this debug log...</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">Starting</span> <span class="ident">Bootloader</span>...
<span class="ident">Displaying</span> <span class="ident">image</span>...
<span class="ident">Image</span> <span class="ident">displayed</span>
<span class="ident">Button</span>: <span class="number">0</span>
[<span class="ident">INF</span>] <span class="ident">Primary</span> <span class="ident">image</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">good</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x2</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x3</span>
[<span class="ident">INF</span>] <span class="ident">Scratch</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">bad</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x2</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x2</span>
[<span class="ident">INF</span>] <span class="ident">Boot</span> <span class="ident">source</span>: <span class="ident">none</span>
[<span class="ident">INF</span>] <span class="ident">Swap</span> <span class="kw">type</span>: <span class="ident">revert</span>
<span class="ident">Button</span>: <span class="number">0</span>
<span class="ident">Button</span>: <span class="number">0</span>
<span class="ident">Bootloader</span> <span class="ident">done</span></pre></div>
<p>Note that <code>Swap type</code> is set to <code>revert</code>, which means that MCUBoot thinks the new firmware is faulty and has swapped the old firmware back.</p>
<p>The old firmware is now in the Internal Flash ROM and begins running...</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">TMP</span> <span class="ident">create</span> <span class="ident">temp_stub_0</span>
<span class="ident">NET</span> <span class="ident">hwid</span> <span class="number">4a</span> <span class="ident">f8</span> <span class="ident">cf</span> <span class="number">95</span> <span class="number">6a</span> <span class="ident">be</span> <span class="ident">c1</span> <span class="ident">f6</span> <span class="number">89</span> <span class="ident">ba</span> <span class="number">12</span> <span class="number">1a</span> 
<span class="ident">NET</span> <span class="ident">standalone</span> <span class="ident">node</span> 
<span class="ident">Testing</span> <span class="ident">flash</span>...
<span class="ident">Read</span> <span class="ident">Internal</span> <span class="ident">Flash</span> <span class="ident">ROM</span>...
<span class="ident">Read</span> <span class="number">0x0</span> <span class="op">+</span> <span class="number">20</span>
<span class="number">0x0000</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x01</span> <span class="number">0x20</span> <span class="number">0xd9</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0008</span>: <span class="number">0x35</span> <span class="number">0x01</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x37</span> <span class="number">0x01</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0010</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0018</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="ident">Read</span> <span class="ident">External</span> <span class="ident">SPI</span> <span class="ident">Flash</span>...
<span class="ident">Read</span> <span class="number">0x0</span> <span class="op">+</span> <span class="number">20</span>
<span class="number">0x0000</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0008</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0010</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0018</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="ident">Flash</span> <span class="ident">OK</span>
<span class="ident">Rust</span> <span class="ident">test</span> <span class="ident">display</span></pre></div>
</li>
<li>
<p><strong>Set the New Firmware Image Status to Pending (Again)</strong> </p>
<p>Let's retry the Firmware Update. We set the status for the new firmware to Pending...</p>
<pre><code class="language-bash"># Set my_sensor_app_1.1.img to pending
sudo ./newtmgr image test -c pinetime \
   66a23f4f8f5766b5150711eb8c7c4be326cebabef37429fd21879f6e0eacffe5
</code></pre>
</li>
<li>
<p><strong>Reboot PineTime (Again)</strong></p>
<p>After rebooting, the new firmware runs correctly...</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">Starting</span> <span class="ident">Bootloader</span>...
<span class="ident">Displaying</span> <span class="ident">image</span>...
<span class="ident">Image</span> <span class="ident">displayed</span>
<span class="ident">Button</span>: <span class="number">0</span>
[<span class="ident">INF</span>] <span class="ident">Primary</span> <span class="ident">image</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">good</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x4</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x1</span>
[<span class="ident">INF</span>] <span class="ident">Scratch</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">bad</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x2</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x2</span>
[<span class="ident">INF</span>] <span class="ident">Boot</span> <span class="ident">source</span>: <span class="ident">none</span>
[<span class="ident">INF</span>] <span class="ident">Swap</span> <span class="kw">type</span>: <span class="ident">test</span>
<span class="ident">Button</span>: <span class="number">0</span>
<span class="ident">Button</span>: <span class="number">0</span>
<span class="ident">Bootloader</span> <span class="ident">done</span></pre></div>
<p><code>Swap type</code> has been set to <code>test</code>, which means that MCUBoot has swapped the new firmware into Internal Flash ROM.</p>
<p>The new firmware runs OK...</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">TMP</span> <span class="ident">create</span> <span class="ident">temp_stub_0</span>
<span class="ident">NET</span> <span class="ident">hwid</span> <span class="number">4a</span> <span class="ident">f8</span> <span class="ident">cf</span> <span class="number">95</span> <span class="number">6a</span> <span class="ident">be</span> <span class="ident">c1</span> <span class="ident">f6</span> <span class="number">89</span> <span class="ident">ba</span> <span class="number">12</span> <span class="number">1a</span> 
<span class="ident">NET</span> <span class="ident">standalone</span> <span class="ident">node</span> 
<span class="ident">Testing</span> <span class="ident">flash</span>...
<span class="ident">Read</span> <span class="ident">Internal</span> <span class="ident">Flash</span> <span class="ident">ROM</span>...
<span class="ident">Read</span> <span class="number">0x0</span> <span class="op">+</span> <span class="number">20</span>
<span class="number">0x0000</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x01</span> <span class="number">0x20</span> <span class="number">0xd9</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0008</span>: <span class="number">0x35</span> <span class="number">0x01</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x37</span> <span class="number">0x01</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0010</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0018</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="ident">Read</span> <span class="ident">External</span> <span class="ident">SPI</span> <span class="ident">Flash</span>...
<span class="ident">Read</span> <span class="number">0x0</span> <span class="op">+</span> <span class="number">20</span>
<span class="number">0x0000</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0008</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0010</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0018</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="ident">Flash</span> <span class="ident">OK</span>
<span class="ident">Rust</span> <span class="ident">test</span> <span class="ident">display</span></pre></div>
</li>
<li>
<p><strong>Confirm the New Firmware Image</strong></p>
<p>We run the <code>image confirm</code> command to confirm and make the uploaded image permanent. 
Since the uploaded image is currently the active image, we can confirm the image setup 
without specifying the image hash value in the command...</p>
<pre><code class="language-bash">sudo ./newtmgr image confirm -c pinetime
</code></pre>
<p>This command shows an error...</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="op">+</span> <span class="ident">sudo</span> .<span class="op">/</span><span class="ident">newtmgr</span> <span class="ident">image</span> <span class="ident">confirm</span> <span class="op">-</span><span class="ident">c</span> <span class="ident">pinetime</span>
<span class="ident">Error</span>: <span class="number">1</span></pre></div>
<p>But when we list the firmware images, the <code>flags</code> for the new firmware (Slot 0) are indeed set to <code>confirmed</code>.</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="op">+</span> <span class="ident">sudo</span> .<span class="op">/</span><span class="ident">newtmgr</span> <span class="ident">image</span> <span class="ident">list</span> <span class="op">-</span><span class="ident">c</span> <span class="ident">pinetime</span>
<span class="ident">Images</span>:
<span class="ident">image</span><span class="op">=</span><span class="number">0</span> <span class="ident">slot</span><span class="op">=</span><span class="number">0</span>
    <span class="ident">version</span>: <span class="number">1.1</span>.<span class="number">0</span>
    <span class="ident">bootable</span>: <span class="bool-val">true</span>
    <span class="ident">flags</span>: <span class="ident">active</span> <span class="ident">confirmed</span>
    <span class="ident">hash</span>: <span class="number">66a23f4f8f5766b5150711eb8c7c4be326cebabef37429fd21879f6e0eacffe5</span>
<span class="ident">image</span><span class="op">=</span><span class="number">0</span> <span class="ident">slot</span><span class="op">=</span><span class="number">1</span>
    <span class="ident">version</span>: <span class="number">1.0</span>.<span class="number">0</span>
    <span class="ident">bootable</span>: <span class="bool-val">true</span>
    <span class="ident">flags</span>: 
    <span class="ident">hash</span>: <span class="number">703ebbf811458b1fad189e64e3a5e0f809cbe6bad883c76b3dd712791c822fb5</span>
<span class="ident">Split</span> <span class="ident">status</span>: <span class="ident">N</span><span class="op">/</span><span class="ident">A</span> (<span class="number">0</span>)</pre></div>
<p>The <code>flags</code> for the old firmware (in External SPI Flash) are set to empty.</p>
</li>
<li>
<p><strong>Reboot PineTime to Verify Firmware Update</strong></p>
<p>Finally we reboot PineTime and verify that the new firmware runs properly...</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">Starting</span> <span class="ident">Bootloader</span>...
<span class="ident">Displaying</span> <span class="ident">image</span>...
<span class="ident">Image</span> <span class="ident">displayed</span>
<span class="ident">Button</span>: <span class="number">0</span>
[<span class="ident">INF</span>] <span class="ident">Primary</span> <span class="ident">image</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">good</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x2</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x1</span>
[<span class="ident">INF</span>] <span class="ident">Scratch</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">bad</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x2</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x2</span>
[<span class="ident">INF</span>] <span class="ident">Boot</span> <span class="ident">source</span>: <span class="ident">none</span>
[<span class="ident">INF</span>] <span class="ident">Swap</span> <span class="kw">type</span>: <span class="ident">none</span>
<span class="ident">Button</span>: <span class="number">0</span>
<span class="ident">Button</span>: <span class="number">0</span>
<span class="ident">Bootloader</span> <span class="ident">done</span>
<span class="ident">TMP</span> <span class="ident">create</span> <span class="ident">temp_stub_0</span>
<span class="ident">NET</span> <span class="ident">hwid</span> <span class="number">4a</span> <span class="ident">f8</span> <span class="ident">cf</span> <span class="number">95</span> <span class="number">6a</span> <span class="ident">be</span> <span class="ident">c1</span> <span class="ident">f6</span> <span class="number">89</span> <span class="ident">ba</span> <span class="number">12</span> <span class="number">1a</span> 
<span class="ident">NET</span> <span class="ident">standalone</span> <span class="ident">node</span> 
<span class="ident">Testing</span> <span class="ident">flash</span>...
<span class="ident">Read</span> <span class="ident">Internal</span> <span class="ident">Flash</span> <span class="ident">ROM</span>...
<span class="ident">Read</span> <span class="number">0x0</span> <span class="op">+</span> <span class="number">20</span>
<span class="number">0x0000</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x01</span> <span class="number">0x20</span> <span class="number">0xd9</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0008</span>: <span class="number">0x35</span> <span class="number">0x01</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x37</span> <span class="number">0x01</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0010</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0018</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="ident">Read</span> <span class="ident">External</span> <span class="ident">SPI</span> <span class="ident">Flash</span>...
<span class="ident">Read</span> <span class="number">0x0</span> <span class="op">+</span> <span class="number">20</span>
<span class="number">0x0000</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0008</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0010</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="number">0x0018</span>: <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> <span class="number">0x00</span> 
<span class="ident">Flash</span> <span class="ident">OK</span>
<span class="ident">Rust</span> <span class="ident">test</span> <span class="ident">display</span></pre></div>
<p>Note that <code>Swap type</code> is <code>none</code>, which means that MCUBoot didn't swap any firmware images.</p>
</li>
</ol>
<p>The steps were derived from this Mynewt tutorial: <a href="https://mynewt.apache.org/latest/tutorials/devmgmt/ota_upgrade_nrf52.html"><code>ota_upgrade_nrf52.html</code></a></p>
<h1 id="update-test-firmware-update-with-freertos" class="section-header"><a href="#update-test-firmware-update-with-freertos">6 Update: Test Firmware Update with FreeRTOS</a></h1>
<p>[ Update: This section is new ]</p>
<p><a href="https://github.com/JF002/Pinetime">FreeRTOS</a> has been tested successfully with Firmware Update on PineTime...</p>
<ol>
<li>
<p>PineTime installed with Mynewt firmware can be updated wirelessly to FreeRTOS...</p>
<ul>
<li>
<p><a href="https://youtu.be/OeHS3SEOB88">Watch on YouTube</a></p>
</li>
<li>
<p><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/download/v4.1.8/dfu-freertos-rotated.mp4">Download the video</a></p>
</li>
</ul>
<p>Here's the PineTime log captured with ST-Link and OpenOCD...</p>

<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="ident">Starting</span> <span class="ident">Bootloader</span>...
<span class="ident">Displaying</span> <span class="ident">image</span>...
<span class="ident">Image</span> <span class="ident">displayed</span>
<span class="ident">Check</span> <span class="ident">button</span>: <span class="number">0</span>
[<span class="ident">INF</span>] <span class="ident">Primary</span> <span class="ident">image</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">good</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x4</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x1</span>
[<span class="ident">INF</span>] <span class="ident">Scratch</span>: <span class="ident">magic</span><span class="op">=</span><span class="ident">bad</span>, <span class="ident">swap_type</span><span class="op">=</span><span class="number">0x1</span>, <span class="ident">copy_done</span><span class="op">=</span><span class="number">0x2</span>, <span class="ident">image_ok</span><span class="op">=</span><span class="number">0x2</span>
[<span class="ident">INF</span>] <span class="ident">Boot</span> <span class="ident">source</span>: <span class="ident">none</span>
[<span class="ident">INF</span>] <span class="ident">Swap</span> <span class="kw">type</span>: <span class="ident">test</span>
<span class="ident">Waiting</span> <span class="number">5</span> <span class="ident">seconds</span> <span class="kw">for</span> <span class="ident">button</span>: <span class="number">0</span>...
<span class="ident">Waited</span> <span class="kw">for</span> <span class="ident">button</span>: <span class="number">0</span>
<span class="ident">Bootloader</span> <span class="ident">done</span>    </pre></div>
</li>
<li>
<p>And after rebooting, PineTime rolls back the firmware from FreeRTOS to Mynewt...</p>
<ul>
<li>
<p><a href="https://youtu.be/0FIYZ9tlI-Q">Watch on YouTube</a></p>
</li>
<li>
<p><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/download/v4.1.8/freertos-rollback-rotated.mp4">Download the video</a></p>
</li>
</ul>
</li>
</ol>
<p>The testing was done with the new version of MCUBoot that relocates the Vector Table...</p>
<p><a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.7"><code>pinetime-rust-mynewt/releases/tag/v4.1.7</code></a></p>
<p>And this FreeRTOS firmware image: <a href="https://github.com/lupyuen/pinetime-rust-mynewt/releases/download/v4.1.5/jf.bin"><code>jf.bin</code></a></p>
<p>With a newer build of FreeRTOS, we were able to switch wirelessly from FreeRTOS to Mynewt...</p>
<p><a href="https://twitter.com/codingfield/status/1264280065799368705?s=20"><code>twitter.com/codingfield/status/1264280065799368705</code></a></p>
<p>Hence we have successfully accomplished Two-Way Wireless Firmware Switching: From Mynewt to FreeRTOS and back.</p>
<h1 id="further-reading" class="section-header"><a href="#further-reading">7 Further Reading</a></h1>
<p><a href="https://github.com/lupyuen/pinetime-rust-mynewt/blob/master/README.md">Check out the other PineTime articles</a></p>
<p><a href="https://lupyuen.github.io/rss.xml">RSS Feed</a></p>

    
</body>
</html>